package com.joker.aigc.chat.dao;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.joker.aigc.chat.domain.entity.Contact;
import com.joker.aigc.chat.domain.entity.Message;
import com.joker.aigc.chat.domain.vo.MessageReadInfoVo;
import com.joker.aigc.chat.mapper.ContactMapper;
import com.joker.aigc.utils.AssertUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 会话
 * @author Joker
 * @since 2025/11/05
 */
@Slf4j
@Service
public class ContactDao extends ServiceImpl<ContactMapper, Contact> {

    public Contact get(Long uid, Long roomId) {
        return lambdaQuery()
                .eq(Contact::getUid, uid)
                .eq(Contact::getRoomId, roomId)
                .one();
    }


    public Integer getReadCount(Message message) {
        return Math.toIntExact(lambdaQuery()
                .eq(Contact::getRoomId, message.getRoomId())
                .ne(Contact::getUid, message.getFromUid())// 不需要查询出自己
                .ge(Contact::getReadTime, message.getCreateTime())
                .count());
    }


    public Integer getTotalCount(Long roomId) {
        return Math.toIntExact(lambdaQuery()
                .eq(Contact::getRoomId, roomId)
                .count());
    }


    public Integer getUnReadCount(Message message) {
        return Math.toIntExact(lambdaQuery()
                .eq(Contact::getRoomId, message.getRoomId())
                .lt(Contact::getReadTime, message.getCreateTime())
                .count());
    }


    public Map<Long, MessageReadInfoVo> getMsgReadInfo(List<Message> messages) {
        Map<Long, List<Message>> roomGroup = messages.stream().collect(Collectors.groupingBy(Message::getRoomId));
        AssertUtil.equal(roomGroup.size(), 1, "只能查相同房间下的消息");
        Long roomId = roomGroup.keySet().iterator().next();
        Integer totalCount = getTotalCount(roomId);
        return messages.stream().map(message -> {
            MessageReadInfoVo readInfoDTO = new MessageReadInfoVo();
            readInfoDTO.setMsgId(message.getId());
            Integer readCount = getReadCount(message);
            readInfoDTO.setReadCount(readCount);
            readInfoDTO.setUnReadCount(totalCount - readCount - 1);
            return readInfoDTO;
        }).collect(Collectors.toMap(MessageReadInfoVo::getMsgId, Function.identity()));
    }

    public Page<Contact> getReadPage(Message message, Page<Contact> cursorPageBaseReq) {

        return lambdaQuery().eq(Contact::getRoomId, message.getRoomId())
                .ne(Contact::getUid, message.getFromUid())// 不需要查询出自己
                .ge(Contact::getReadTime, message.getCreateTime())// 已读时间大于等于消息发送时间
                .page(cursorPageBaseReq);
    }

    public Page<Contact> getUnReadPage(Message message, Page<Contact> cursorPageBaseReq) {
        return lambdaQuery().eq(Contact::getRoomId, message.getRoomId())
                .ne(Contact::getUid, message.getFromUid())// 不需要查询出自己
                .le(Contact::getReadTime, message.getCreateTime())// 已读时间小于消息发送时间
                .page(cursorPageBaseReq);
    }

    public List<Contact> getByRoomIds(List<Long> roomIds, Long uid) {
        return lambdaQuery()
                .in(Contact::getRoomId, roomIds)
                .eq(Contact::getUid, uid)
                .list();
    }

    /**
     * 更新所有人的会话时间，没有就直接插入
     */
    @Transactional
    public void refreshOrCreateActiveTime(Long roomId, Long msgId, Date activeTime) {
        List<Contact> contacts = lambdaQuery().eq(Contact::getRoomId, roomId).list();
        if (CollectionUtil.isNotEmpty(contacts)) {
            contacts.forEach(item -> {
                item.setActiveTime(activeTime);
                item.setLastMsgId(msgId);
            });
            saveOrUpdateBatch(contacts);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void refreshReadTime(Long roomId, List<Long> memberUidList, Long msgId, Date activeTime) {
        List<Contact> contacts = lambdaQuery().eq(Contact::getRoomId, roomId).in(Contact::getUid, memberUidList).list();
        if (CollUtil.isNotEmpty(contacts)) {
            contacts.forEach(item -> {
                item.setReadTime(activeTime);
                item.setLastMsgId(msgId);
            });
            saveOrUpdateBatch(contacts);
        }
    }

    /**
     * 根据房间ID删除会话
     *
     * @param roomId  房间ID
     * @param uidList 群成员列表
     * @return 是否删除成功
     */

    public Boolean removeByRoomId(Long roomId, List<Long> uidList) {
        if (CollectionUtil.isNotEmpty(uidList)) {
            LambdaQueryWrapper<Contact> wrapper = new QueryWrapper<Contact>().lambda()
                    .eq(Contact::getRoomId, roomId)
                    .in(Contact::getUid, uidList);
            return this.remove(wrapper);
        }
        return false;
    }

}
